package be.android.forap.sync;

import be.android.forap.Constants;
import be.android.forap.ForApAuthenticator;
import be.android.forap.R;
import be.android.forap.gui.AccountFailActivity;
import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.accounts.NetworkErrorException;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.ContactsContract;
import android.util.Log;

public class AccountAuthenticatorService extends Service {

	private static final String TAG = "AccountAuthenticatorService";

	private static AccountAuthenticator sAccountAuthenticator = null;

	public AccountAuthenticatorService() {
		super();
	}

	@Override
	public IBinder onBind(Intent intent) {
		IBinder ret = null;
		if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT))
			ret = getAuthenticator().getIBinder();
		return ret;
	}

	/*public static Boolean addAccount(Context ctx, String username, String password) {
		Boolean result = AccountAuthenticatorImpl.addAccount(ctx, username, password);
		return result;			
	}

	public static void addAccount(Context ctx, String username, String password, Parcelable response) {
		AccountAuthenticatorResponse authResponse = (AccountAuthenticatorResponse)response;
		Bundle result = AccountAuthenticatorImpl.addAccountReturnBundle(ctx, username, password);
		if(authResponse != null){
			authResponse.onResult(result);
		}

	}*/

	public static Boolean hasForApAccount(Context ctx) {
		return AccountAuthenticator.hasForApAccount(ctx);
	}

	public static void removeForApAccount(Context ctx) {
		AccountAuthenticator.removeForApAccount(ctx);
	}

	public static void resyncAccount(Context context) {
		AccountManager am = AccountManager.get(context);
		Account[] accounts = am.getAccountsByType(context.getString(R.string.ACCOUNT_TYPE));
		if(ContentResolver.getSyncAutomatically(accounts[0], ContactsContract.AUTHORITY)) {
			//Try turning it off and on again
			ContentResolver.setSyncAutomatically(accounts[0], ContactsContract.AUTHORITY, false);
			ContentResolver.setSyncAutomatically(accounts[0], ContactsContract.AUTHORITY, true);
		}
	}

	public static void forceSyncAccount(Context context) {
		Log.d(TAG, "FORCE SYNC");
		AccountManager am = AccountManager.get(context);
		Account[] accounts = am.getAccountsByType(context.getString(R.string.ACCOUNT_TYPE));
		for(int i=0;i<accounts.length;i++){
			Log.d(TAG, "Account name: " + accounts[i].name + " type: "+ accounts[i].type);
		}
		Bundle bundle = new Bundle();
		bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
		bundle.putBoolean(ContentResolver.SYNC_EXTRAS_FORCE, true);
		bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
		ContentResolver.requestSync(accounts[0], ContactsContract.AUTHORITY, bundle);
	}

	private AccountAuthenticator getAuthenticator() {
		if (sAccountAuthenticator == null)
			sAccountAuthenticator = new AccountAuthenticator(this);
		return sAccountAuthenticator;
	}


	private static class AccountAuthenticator extends AbstractAccountAuthenticator {

		private static final String TAG = "AccountAuthenticatorImpl";
		// Authentication Service context
		private Context mContext;

		public AccountAuthenticator(Context context) {
			super(context);
			mContext = context;
		}

		/*public static Boolean addAccount(Context ctx, String username, String password) {
			Account account = new Account(username, Constants.ACCOUNT_TYPE);
			AccountManager am = AccountManager.get(ctx);
			if (am.addAccountExplicitly(account, password, null)) 
				// Set contacts sync for this account.
				ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
				return true;
			return false;
		}


		public static Bundle addAccountReturnBundle(Context ctx, String username, String password) {
			Bundle result = null;
			Account account = new Account(username, ctx.getString(R.string.ACCOUNT_TYPE));
			AccountManager am = AccountManager.get(ctx);
			if (am.addAccountExplicitly(account, password, null)) {
				result = new Bundle();
				result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
				result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
			}
			return result;
		}*/

		public static Boolean hasForApAccount(Context ctx) {
			//TODO
			AccountManager am = AccountManager.get(ctx);
			Account[] accounts = am.getAccountsByType(ctx.getString(R.string.ACCOUNT_TYPE));
			if(accounts != null && accounts.length > 0)
				return true;
			else
				return false;
		}

		public static void removeForApAccount(Context ctx) {
			//TODO
			AccountManager am = AccountManager.get(ctx);
			Account[] accounts = am.getAccountsByType(ctx.getString(R.string.ACCOUNT_TYPE));
			for(Account account : accounts) {
				am.removeAccount(account, null, null);
			}
		}

		/* (non-Javadoc)
		 * @see android.accounts.AbstractAccountAuthenticator#addAccount(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle)
		 */
		/*
		 * The user has requested to add a new account to the system.  
		 * We return an intent that will launch our login screen if the user has not logged in yet,
		 * otherwise our activity will just pass the user's credentials on to the account manager.
		 */
		@Override
		public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
				throws NetworkErrorException {
			Bundle result;

			if(hasForApAccount(mContext)) {
				result = new Bundle();
				Intent i = new Intent(mContext, AccountFailActivity.class);
				i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
				result.putParcelable(AccountManager.KEY_INTENT, i);
				return result;
			} else {
				result = new Bundle();
				Intent i = new Intent(mContext, ForApAuthenticator.class);
				i.setAction("be.android.forap.sync.LOGIN_ONLY");
				i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
				result.putParcelable(AccountManager.KEY_INTENT, i);
			}
			return result;
		}


		@Override
		public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) {
			// TODO Auto-generated method stub
			Log.i(TAG, "confirmCredentials");
			return null;
		}

		@Override
		public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
			// TODO Auto-generated method stub
			Log.i(TAG, "editProperties");
			return null;
		}

		@Override
		public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
			Log.v(TAG, "getAuthToken()");

			// If the caller requested an authToken type we don't support, then
			// return an error
			if (!authTokenType.equals(Constants.AUTHTOKEN_TYPE)) {
				final Bundle result = new Bundle();
				result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authTokenType");
				return result;
			}

			/*if(DropboxUtil.isLoggedInDropBox(mContext)){
	        	final Bundle result = new Bundle();
                result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
                result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
                //result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
                return result;
	        }*/
			return null;
			//TODO

		}

		@Override
		public String getAuthTokenLabel(String authTokenType) {
			// TODO Auto-generated method stub
			Log.i(TAG, "getAuthTokenLabel");
			return null;
		}

		@Override
		public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
			// This call is used to query whether the Authenticator supports
			// specific features. We don't expect to get called, so we always
			// return false (no) for any queries.
			Log.v(TAG, "hasFeatures()");
			final Bundle result = new Bundle();
			result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
			return result;

		}

		@Override
		public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) {
			// TODO Auto-generated method stub
			Log.i(TAG, "updateCredentials");
			return null;
		}
		/*



    @Override
    public Bundle confirmCredentials(
            AccountAuthenticatorResponse response, Account account, Bundle options) {
        Log.v(TAG, "confirmCredentials()");
        return null;
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
        Log.v(TAG, "editProperties()");
        throw new UnsupportedOperationException();
    }

    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
            String authTokenType, Bundle loginOptions) throws NetworkErrorException {
        Log.v(TAG, "getAuthToken()");

        // If the caller requested an authToken type we don't support, then
        // return an error
        if (!authTokenType.equals(Constants.AUTHTOKEN_TYPE)) {
            final Bundle result = new Bundle();
            result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authTokenType");
            return result;
        }

        // Extract the username and password from the Account Manager, and ask
        // the server for an appropriate AuthToken.
        final AccountManager am = AccountManager.get(mContext);
        final String password = am.getPassword(account);
        if (password != null) {
            final String authToken = NetworkUtilities.authenticate(account.name, password);
            if (!TextUtils.isEmpty(authToken)) {
                final Bundle result = new Bundle();
                result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
                result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
                result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
                return result;
            }
        }

        // If we get here, then we couldn't access the user's password - so we
        // need to re-prompt them for their credentials. We do that by creating
        // an intent to display our AuthenticatorActivity panel.
        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
        intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
        intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, authTokenType);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
        final Bundle bundle = new Bundle();
        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
        return bundle;
    }

    @Override
    public String getAuthTokenLabel(String authTokenType) {
        // null means we don't support multiple authToken types
        Log.v(TAG, "getAuthTokenLabel()");
        return null;
    }

    @Override
    public Bundle hasFeatures(
            AccountAuthenticatorResponse response, Account account, String[] features) {
        // This call is used to query whether the Authenticator supports
        // specific features. We don't expect to get called, so we always
        // return false (no) for any queries.
        Log.v(TAG, "hasFeatures()");
        final Bundle result = new Bundle();
        result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
        return result;
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
            String authTokenType, Bundle loginOptions) {
        Log.v(TAG, "updateCredentials()");
        return null;
    }

		 */
	}
}
